const escapeForRegex = require('escape-string-regexp');
import { Meteor } from 'meteor/meteor';

MindMaps = new Mongo.Collection('mindMaps');

MindMaps.attachSchema(
  new SimpleSchema({
    _id: {
      type: String,
    },
    name: {
      /**
       * the title of the card
       */
      type: String,
      optional: true,
      defaultValue: '',
    },
    userId: {
      type: String,
      autoValue() {
        // eslint-disable-line consistent-return
        if (this.isInsert && !this.isSet) {
          return this.userId;
        }
      },
    },
    content: {
      type: String,
      optional: true,
    },
    sort: {
      type: Number,
      decimal: true,
      defaultValue: 0,
    },
    archived: {
      /**
       * Is the board archived?
       */
      type: Boolean,
      // eslint-disable-next-line consistent-return
      autoValue() {
        if (this.isInsert && !this.isSet) {
          return false;
        }
      },
    },
    archivedAt: {
      /**
       * latest archiving date
       */
      type: Date,
      optional: true,
    },
    createdAt: {
      type: Date,
      optional: true,
      // eslint-disable-next-line consistent-return
      autoValue() {
        if (this.isInsert) {
          return new Date();
        } else if (this.isUpsert) {
          return { $setOnInsert: new Date() };
        } else {
          this.unset();
        }
      },
    },
    modifiedAt: {
      type: Date,
      denyUpdate: false,
      // eslint-disable-next-line consistent-return
      autoValue() {
        if (this.isInsert || this.isUpsert || this.isUpdate) {
          return new Date();
        } else {
          this.unset();
        }
      },
    },
  }),
);

MindMaps.allow({
  insert: Meteor.userId,
  remove(userId) {
    const user = Users.findOne(userId);
    return user && user.isAdmin;
  },
  update(userId) {
    const user = Users.findOne(userId);
    return user && user.isAdmin;
  },
  fetch: ['userId'],
});

if (Meteor.isServer) {
  Meteor.startup(() => {
    MindMaps._collection._ensureIndex({ modifiedAt: -1 });
    MindMaps._collection._ensureIndex({ userId: 1 });
  });

  Meteor.methods({
    archiveMindMap(mindMapId) {
      check(mindMapId, String);
      const mindMap = MindMaps.findOne(mindMapId);
      if (mindMap) {
        const userId = Meteor.userId();
        if (userId === mindMap.userId) {
          mindMap.archive();
          return true;
        } else throw new Meteor.Error('需要成为脑图成员才能执行此操作');
      } else throw new Meteor.Error('该脑图不存在');
    },
  });
}

MindMaps.mutations({
  archive() {
    return { $set: { archived: true, archivedAt: new Date() } };
  },
  move(sortIndex) {
    return { $set: { sort: sortIndex } };
  },
  restore() {
    return { $set: { archived: false } };
  },
});

MindMaps.helpers({
  copy() {
    delete this._id;
    this.name = this.copyName();
    const _id = MindMaps.insert(this);
    return _id;
  },
  /**
   * Return a unique name based on the current name
   *
   * @returns {string|null}
   */
  copyName() {
    return MindMaps.uniqueName(this.name);
  },
});

MindMaps.uniqueName = name => {
  const m = name.match(
    new RegExp('^(?<name>.*?)\\s*(\\[(?<num>\\d+)]\\s*$|\\s*$)'),
  );
  const base = escapeForRegex(m.groups.name);
  let num = 0;
  MindMaps.find({ name: new RegExp(`^${base}\\s*\\[\\d+]\\s*$`) }).forEach(
    mindMap => {
      const m = mindMap.name.match(
        new RegExp('^(?<name>.*?)\\s*\\[(?<num>\\d+)]\\s*$'),
      );
      if (m) {
        const n = parseInt(m.groups.num, 10);
        num = num < n ? n : num;
      }
    },
  );

  if (num > 0) {
    return `${base} [${num + 1}]`;
  }

  return name;
};

//脑图访问数据库 rest api
if (Meteor.isServer) {
  /**
   * @operation get_swimlane_cards
   * @summary get all cards attached to a swimlane
   *
   * @param {string} boardId the board ID
   * @param {string} swimlaneId the swimlane ID
   * @return_type [{_id: string,
   *                title: string,
   *                description: string,
   *                listId: string}]
   */

  JsonRoutes.add('GET', '/api/mindMaps/:mindMapId/:userId', function(req, res) {
    const paramMindMapId = req.params.mindMapId;
    Authentication.checkMindMapAccess(req.params.userId, paramMindMapId);
    JsonRoutes.sendResult(res, {
      code: 200,
      data: MindMaps.find({
        _id: paramMindMapId,
      }).map(function(doc) {
        return {
          _id: doc._id,
          content: doc.content,
          name: doc.name,
        };
      }),
    });
  });
  //修改
  JsonRoutes.add('PUT', '/api/mindMaps/:mindMapId', function(req, res) {
    try {
      //Authentication.checkUserId(req.userId);
      const paramMindMapId = req.params.mindMapId;
      const paramContent = req.body.content;
      MindMaps.direct.update(
        {
          _id: paramMindMapId,
          archived: false,
        },
        {
          $set: {
            content: paramContent,
            modifiedAt: new Date(),
          },
        },
      );
      JsonRoutes.sendResult(res, {
        code: 200,
        data: '保存成功!',
      });
    } catch (error) {
      JsonRoutes.sendResult(res, {
        code: 200,
        data: `保存失败!${error}`,
      });
    }
  });

  //修改脑图名称
  JsonRoutes.add('POST', '/api/mindMapsName/:mindMapId', function(req, res) {
    try {
      //Authentication.checkUserId(req.userId);
      const paramMindMapId = req.params.mindMapId;
      const paramName = req.body.mindMapName;
      MindMaps.direct.update(
        {
          _id: paramMindMapId,
          archived: false,
        },
        {
          $set: {
            name: paramName,
            modifiedAt: new Date(),
          },
        },
      );
      JsonRoutes.sendResult(res, {
        code: 200,
        data: '重命名成功!',
      });
    } catch (error) {
      JsonRoutes.sendResult(res, {
        code: 200,
        data: '重命名失败!' + error,
      });
    }
  });
}

export default MindMaps;
